package de.tuberlin.dima.minidb.api;


import de.tuberlin.dima.minidb.parser.SQLParser;


/**
 * A simple abstract factory-like extension point that supplies the actual implementation 
 * of classes being initialized with the class name of the concrete factory.
 *  
 * @author Stephan Ewen (sewen@cs.tu-berlin.de)
 */
public abstract class ExtensionFactory
{
	
	/**
	 * The singleton instance of this class' implementation.
	 */
	private static ExtensionFactory singletonInstance;
	
	
	/**
	 * Gets the actual implementation of this <code>ExtansionFactory</code>.
	 * This method can only be called after <code>init</code> has been called.
	 * 
	 * @return The implementation of the <code>ExtansionFactory</code>.
	 * @throws IllegalStateException If <code>init</code> has not been called on
	 *                               the <code>ExtansionFactory</code>.
	 */
	public static ExtensionFactory getExtensionFactory() throws IllegalStateException
	{
		if (singletonInstance == null) {
			throw new IllegalStateException("Registry has not been initialized!");
		} else {
			return singletonInstance;
		}
	}
	
	/**
	 * Initializes this <code>ExtensionFactory</code> with the class name of the
	 * actual implementation.
	 * 
	 * @param implementationClass The name of the class that holds the actual
	 *         implementation.
	 * @throws ExtensionInitFailedException If the class could for some reason not be
	 *          initialized. The Exception contains further information.
	 */
	public static void init(String implementationClass) throws ExtensionInitFailedException
	{
		try
		{
			Class<?> gc = Class.forName(implementationClass);
			Class<? extends ExtensionFactory> ec = gc.asSubclass(ExtensionFactory.class);
			
			singletonInstance = ec.newInstance();
		}
		catch (ClassNotFoundException cnfex) {
			throw new ExtensionInitFailedException("The class '" + implementationClass +
					"' was not found. Check that it is in the class path.", cnfex);
		}
		catch (ExceptionInInitializerError eiiex) {
			throw new ExtensionInitFailedException("The class '" + implementationClass +
					"' could not be loaded, because errors occurred in the initializers.",
					eiiex);
		}
		catch (ClassCastException ccex) {
			throw new ExtensionInitFailedException("The class '" + implementationClass +
					"' is not a subclass of '" + ExtensionFactory.class.getName() +
					"'.", ccex);
		}
		catch (Throwable t) {
			throw new ExtensionInitFailedException("The class '" + implementationClass +
					"' could not be loaded due to an unknown error.", t);
		}
	}
	
	
	
	
	
	
	/**
	 * Gets an implementation for the <code>SQLParser</code>
	 * 
	 * @param sqlStatement The statement to be parsed by the parser.
	 * @return An SQLParser implementation.
	 */
	public abstract SQLParser getParser(String sqlStatement);
}
